import { FormSchema } from '/@/components/Form';
import { getDeviceTypes } from '/@/api/thingsborad/entity/entity';
import { getQueues } from '/@/api/thingsborad/profile/assetProfile/assetProfile';
import { useDebounceFn } from '@vueuse/shared';
import { ref } from 'vue';
import {
  getEntityDeviceList,
  getTenantAssetInfos,
  getTenantEntityViews,
} from '/@/api/thingsborad/entity/entity';
import { getTenant } from '/@/api/thingsborad/entity/entity';
import { getCustomersList } from '/@/api/thingsborad/customers/customers';
import { getUserList } from '/@/api/thingsborad/notification/notification';
import { getDashboard } from '/@/api/thingsborad/dashboards/dashboard';
import { getEdgeList } from '/@/api/thingsborad/edge/edge';
import { useUserStore } from '/@/store/modules/user';
import { getRuleChainList } from '/@/api/thingsborad/profile/deviceProfile/deviceProfile';
import { getTemplatesList, getTargetsList } from '/@/api/thingsborad/notification/notification';

const userStore = useUserStore();
const tentantId = userStore.getUserInfo.tenantId.id;
const search = ref('');
const Apis = {
  DEVICE: {
    api: getEntityDeviceList,
    params: { page: 0, pageSize: 50, sortProperty: 'name', sortOrder: 'ASC', textSearch: search },
  },
  ASSET: {
    api: getTenantAssetInfos,
    params: { page: 0, pageSize: 50, sortProperty: 'name', sortOrder: 'ASC', textSearch: search },
  },
  ENTITY_VIEW: {
    api: getTenantEntityViews,
    params: { page: 0, pageSize: 50, sortProperty: 'name', sortOrder: 'ASC', textSearch: search },
  },
  TENANT: {
    api: getTenant,
    params: tentantId,
  },
  CUSTOMER: {
    api: getCustomersList,
    params: { page: 0, pageSize: 50, sortProperty: 'title', sortOrder: 'ASC', textSearch: search },
  },
  USER: {
    api: getUserList,
    params: { page: 0, pageSize: 50, sortProperty: 'email', sortOrder: 'ASC', textSearch: search },
  },
  DASHBOARD: {
    api: getDashboard,
    params: { page: 0, pageSize: 50, sortProperty: 'title', sortOrder: 'ASC', textSearch: search },
  },
  EDGE: {
    api: getEdgeList,
    params: { page: 0, pageSize: 50, sortProperty: 'name', sortOrder: 'ASC', textSearch: search },
  },
};

export const formObject: Recordable<FormSchema[]> = {
  'org.thingsboard.rule.engine.filter.TbCheckAlarmStatusNode': [
    {
      field: 'alarmStatusList',
      label: 'Alarm status',
      component: 'CheckboxGroup',
      componentProps: {
        options: [
          {
            label: '激活未确认',
            value: 'ACTIVE_UNACK',
          },
          {
            label: '激活已确认',
            value: 'ACTIVE_ACK',
          },
          {
            label: '清除未确认',
            value: 'CLEARED_UNACK',
          },
          {
            label: '清除已确认',
            value: 'CLEARED_ACK',
          },
        ],
      },
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.filter.TbCheckMessageNode': [
    {
      field: 'messageNames',
      label: 'Message field names',
      component: 'Select',
      componentProps: {
        placeholder: '请输入Message field names',
        mode: 'tags',
        open: false,
      },
    },
    {
      field: 'metadataNames',
      label: 'Metadata field names',
      component: 'Select',
      componentProps: {
        placeholder: '请输入Metadata field names',
        mode: 'tags',
        open: false,
      },
    },
    {
      field: 'checkAllKeys',
      label: 'Check that all specified fields are present',
      component: 'Switch',
    },
  ],
  'org.thingsboard.rule.engine.filter.TbCheckRelationNode': [
    {
      field: 'direction',
      label: '方向',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: '从originator',
            value: 'FROM',
          },
          {
            label: '到originator',
            value: 'TO',
          },
        ],
      },
      required: true,
    },
    {
      field: 'relationType',
      label: '关系类型',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Contains',
            value: 'Contains',
          },
          {
            label: 'Manages',
            value: 'Manages',
          },
        ],
      },
      required: true,
    },
    {
      field: 'checkForSingleEntity',
      label: 'Check relation to specific entity',
      component: 'Switch',
      defaultValue: false,
    },
    {
      field: 'entityType',
      label: '实体类型',
      component: 'Select',
      componentProps: ({ formActionType }) => {
        return {
          placeholder: '请选择实体类型',
          options: [
            {
              label: '资产',
              value: 'ASSET',
            },
            {
              label: '设备',
              value: 'DEVICE',
            },
            {
              label: '用户',
              value: 'USER',
            },
          ],
          onChange: (value: string) => {
            const { updateSchema } = formActionType;
            let label = '';
            switch (value) {
              case 'ASSET':
                label = '资产';
                break;
              case 'DEVICE':
                label = '设备';
                break;
              case 'USER':
                label = '用户';
                break;
            }
            updateSchema({
              field: 'entityId',
              label,
              componentProps: {
                placeholder: `请选择${label}`,
                api: Apis[value].api,
                params: Apis[value].params,
                onSearch: (value: string) => {
                  search.value = value;
                },
              },
            });
          },
        };
      },
      ifShow: ({ values }) => values.checkForSingleEntity,
    },
    {
      field: 'entityId',
      label: '设备',
      component: 'ApiSelect',
      componentProps: {
        resultField: 'data',
        labelField: 'name',
        valueField: 'id.id',
        showSearch: true,
        immediate: false,
        listHeight: 160,
      },
      ifShow: ({ values }) => values.checkForSingleEntity && values.entityType,
    },
  ],
  'org.thingsboard.rule.engine.filter.TbOriginatorTypeFilterNode': [
    {
      field: 'originatorTypes',
      label: '实体类型',
      component: 'Select',
      componentProps: {
        placeholder: '请选择实体类型',
        maxTagCount: 'responsive',
        mode: 'tags',
        options: [
          { label: '设备', value: 'DEVICE' },
          { label: '资产', value: 'ASSET' },
          { label: '实体视图', value: 'ENTITY_VIEW' },
          { label: '租户', value: 'TENANT' },
          { label: '客户', value: 'CUSTOMER' },
          { label: '用户', value: 'USER' },
          { label: '仪表盘', value: 'DASHBOARD' },
          { label: '规则链', value: 'RULE_CHAIN' },
          { label: '规则节点', value: 'RULE_NODE' },
        ],
      },
      required: true,
      defaultValue: 'DEVICE',
    },
  ],
  'org.thingsboard.rule.engine.geo.TbGpsGeofencingFilterNode': [
    {
      field: 'latitudeKeyName',
      label: 'Latitude field name',
      component: 'Input',
      required: true,
      defaultValue: 'latitude',
    },
    {
      field: 'longitudeKeyName',
      label: 'Longitude field name',
      component: 'Input',
      required: true,
      defaultValue: 'longitude',
    },
    {
      field: 'perimeterType',
      label: 'Perimeter type',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Circle',
            value: 'CIRCLE',
          },
          {
            label: 'Polygon',
            value: 'POLYGON',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'POLYGON',
      required: true,
    },
    {
      field: 'fetchPerimeterInfoFromMessageMetadata',
      label: 'Fetch perimeter information from metadata',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'polygonsDefinition',
      label: 'polygonsDefinition',
      component: 'Input',
      required: true,
      show: ({ model }) =>
        !model.fetchPerimeterInfoFromMessageMetadata && model.perimeterType === 'POLYGON',
    },
    {
      field: 'perimeterKeyName',
      label: 'Perimeter key name',
      component: 'Input',
      required: true,
      show: ({ model }) => model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'centerLatitude',
      label: 'Center latitude',
      component: 'InputNumber',
      componentProps: {
        min: -90,
        max: 90,
        step: 0.1,
      },
      required: true,
      show: ({ model }) =>
        model.perimeterType === 'CIRCLE' && !model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'centerLongitude',
      label: 'Center longitude',
      component: 'InputNumber',
      componentProps: {
        min: -90,
        max: 90,
        step: 0.1,
      },
      required: true,
      show: ({ model }) =>
        model.perimeterType === 'CIRCLE' && !model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'range',
      label: 'Range',
      component: 'InputNumber',
      componentProps: {
        min: 0,
        step: 0.1,
      },
      required: true,
      show: ({ model }) =>
        model.perimeterType === 'CIRCLE' && !model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'rangeUnit',
      label: 'Range unit',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Meter',
            value: 'METER',
          },
          {
            label: 'Kilometer',
            value: 'KILOMETER',
          },
          {
            label: 'Foot',
            value: 'FOOT',
          },
          {
            label: 'Mile',
            value: 'MILE',
          },
          {
            label: 'Nautical mile',
            value: 'NAUTICAL_MILE',
          },
        ],
      },
      defaultValue: 'METER',
      show: ({ model }) =>
        model.perimeterType === 'CIRCLE' && !model.fetchPerimeterInfoFromMessageMetadata,
    },
  ],
  'org.thingsboard.rule.engine.filter.TbMsgTypeFilterNode': [
    {
      field: 'messageTypes',
      label: '消息类型',
      component: 'Select',
      componentProps: {
        placeholder: '请选择消息类型',
        mode: 'multiple',
        listHeight: 120,
        maxTagCount: 'responsive',
        options: [
          { label: 'POST_ATTRIBUTES_REQUEST', value: 'POST_ATTRIBUTES_REQUEST' },
          { label: 'POST_TELEMETRY_REQUEST', value: 'POST_TELEMETRY_REQUEST' },
          { label: 'TO_SERVER_RPC_REQUEST', value: 'TO_SERVER_RPC_REQUEST' },
          { label: 'RPC_CALL_FROM_SERVER_TO_DEVICE', value: 'RPC_CALL_FROM_SERVER_TO_DEVICE' },
          { label: 'RPC_QUEUED', value: 'RPC_QUEUED' },
          { label: 'RPC_SENT', value: 'RPC_SENT' },
          { label: 'RPC_DELIVERED', value: 'RPC_DELIVERED' },
          { label: 'RPC_SUCCESSFUL', value: 'RPC_SUCCESSFUL' },
          { label: 'RPC_TIMEOUT', value: 'RPC_TIMEOUT' },
          { label: 'RPC_EXPIRED', value: 'RPC_EXPIRED' },
          { label: 'RPC_FAILED', value: 'RPC_FAILED' },
          { label: 'RPC_DELETED', value: 'RPC_DELETED' },
          { label: 'ACTIVITY_EVENT', value: 'ACTIVITY_EVENT' },
          { label: 'INACTIVITY_EVENT', value: 'INACTIVITY_EVENT' },
          { label: 'CONNECT_EVENT', value: 'CONNECT_EVENT' },
          { label: 'DISCONNECT_EVENT', value: 'DISCONNECT_EVENT' },
          { label: 'ENTITY_CREATED', value: 'ENTITY_CREATED' },
          { label: 'ENTITY_UPDATED', value: 'ENTITY_UPDATED' },
          { label: 'ENTITY_DELETED', value: 'ENTITY_DELETED' },
          { label: 'ENTITY_ASSIGNED', value: 'ENTITY_ASSIGNED' },
          { label: 'ENTITY_UNASSIGNED', value: 'ENTITY_UNASSIGNED' },
          { label: 'ATTRIBUTES_UPDATED', value: 'ATTRIBUTES_UPDATED' },
          { label: 'ATTRIBUTES_DELETED', value: 'ATTRIBUTES_DELETED' },
          { label: 'ALARM_ACKNOWLEDGED', value: 'ALARM_ACKNOWLEDGED' },
          { label: 'ALARM_CLEARED', value: 'ALARM_CLEARED' },
          { label: 'ALARM_ASSIGNED', value: 'ALARM_ASSIGNED' },
          { label: 'ALARM_UNASSIGNED', value: 'ALARM_UNASSIGNED' },
          { label: 'COMMENT_CREATED', value: 'COMMENT_CREATED' },
          { label: 'COMMENT_UPDATED', value: 'COMMENT_UPDATED' },
          { label: 'ENTITY_ASSIGNED_FROM_TENANT', value: 'ENTITY_ASSIGNED_FROM_TENANT' },
          { label: 'ENTITY_ASSIGNED_TO_TENANT', value: 'ENTITY_ASSIGNED_TO_TENANT' },
          { label: 'TIMESERIES_UPDATED', value: 'TIMESERIES_UPDATED' },
          { label: 'TIMESERIES_DELETED', value: 'TIMESERIES_DELETED' },
        ],
      },
      required: true,
      defaultValue: ['POST_ATTRIBUTES_REQUEST', 'POST_TELEMETRY_REQUEST', 'TO_SERVER_RPC_REQUEST'],
    },
  ],
  'org.thingsboard.rule.engine.filter.TbJsFilterNode': [
    {
      field: 'scriptLang',
      label: '',
      component: 'RadioButtonGroup',
      slot: 'scriptLangSlot',
      componentProps: {
        options: [
          {
            label: 'TBEL',
            value: 'TBEL',
          },
          {
            label: 'JavaScript',
            value: 'JS',
          },
        ],
      },
      colProps: {
        span: 24,
      },
      defaultValue: 'TBEL',
    },
    {
      field: 'tbelScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: 'return msg.temperature > 20;',
    },
    {
      field: 'jsScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: 'return msg.temperature > 20;',
    },
  ],
  'org.thingsboard.rule.engine.filter.TbJsSwitchNode': [
    {
      field: 'scriptLang',
      label: '',
      component: 'RadioButtonGroup',
      slot: 'scriptLangSlot',
      componentProps: {
        options: [
          {
            label: 'TBEL',
            value: 'TBEL',
          },
          {
            label: 'JavaScript',
            value: 'JS',
          },
        ],
      },
      colProps: {
        span: 24,
      },
      defaultValue: 'TBEL',
    },
    {
      field: 'tbelScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `function nextRelation(metadata, msg) {
    return ['one','nine'];
}
if(msgType == 'POST_TELEMETRY_REQUEST') {
    return ['two'];
}
return nextRelation(metadata, msg);`,
    },
    {
      field: 'jsScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `function nextRelation(metadata, msg) {
    return ['one','nine'];
}
if(msgType == 'POST_TELEMETRY_REQUEST') {
    return ['two'];
}
return nextRelation(metadata, msg);`,
    },
  ],
  'org.thingsboard.rule.engine.metadata.CalculateDeltaNode': [
    {
      field: 'inputValueKey',
      label: 'Input value key',
      component: 'Input',
      required: true,
      defaultValue: 'pulseCounter',
    },
    {
      field: 'outputValueKey',
      label: 'Output value key',
      component: 'Input',
      required: true,
      defaultValue: 'delta',
    },
    {
      field: 'round',
      label: 'Number of digits after floating point',
      component: 'InputNumber',
      componentProps: {
        min: 0,
        max: 15,
      },
    },
    {
      field: 'tellFailureIfDeltaIsNegative',
      label: 'Tell Failure if delta is negative',
      component: 'Switch',
      defaultValue: true,
    },
    {
      field: 'useCache',
      label: 'Use caching',
      component: 'Switch',
      defaultValue: true,
    },
    {
      field: 'addPeriodBetweenMsgs',
      label: 'Add the time difference between "pulseCounter" readings',
      component: 'Switch',
      defaultValue: false,
    },
    {
      field: 'periodValueKey',
      label: 'Period value key',
      component: 'Input',
      required: true,
      defaultValue: 'periodInMs',
      ifShow: (value) => {
        return value.model.addPeriodBetweenMsgs;
      },
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetCustomerAttributeNode': [
    {
      field: 'dataToFetch',
      label: "Mapping of customer's",
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Attributes', value: 'ATTRIBUTES' },
          { label: 'Latest telemetry', value: 'LATEST_TELEMETRY' },
        ],
      },
      defaultValue: 'ATTRIBUTES',
      required: true,
      colProps: {
        span: 24,
      },
    },
    {
      field: 'dataMapping',
      label: '',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Source attribute key',
        rightTitle: 'Target key',
      },
      colProps: {
        span: 24,
      },
    },
    {
      field: 'fetchTo',
      label: 'Add mapped latest telemetry to',
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Message', value: 'DATA' },
          { label: 'Metadata', value: 'METADATA' },
        ],
      },
      defaultValue: 'DATA',
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetCustomerDetailsNode': [
    {
      field: 'detailsList',
      label: 'Select details',
      component: 'Select',
      componentProps: {
        maxTagCount: 'responsive',
        mode: 'multiple',
        options: [
          { label: 'ID', value: 'ID' },
          { label: 'TITLE', value: 'TITLE' },
          { label: 'COUNTRY', value: 'COUNTRY' },
          { label: 'STATE', value: 'STATE' },
          { label: 'CITY', value: 'CITY' },
          { label: 'ZIP', value: 'ZIP' },
          { label: 'ADDRESS', value: 'ADDRESS' },
          { label: 'ADDRESS2', value: 'ADDRESS2' },
          { label: 'PHONE', value: 'PHONE' },
          { label: 'EMAIL', value: 'EMAIL' },
          { label: 'ADDITIONAL_INFO', value: 'ADDITIONAL_INFO' },
        ],
      },
      required: true,
    },
    {
      field: 'fetchTo',
      label: 'Add selected details to',
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Message', value: 'DATA' },
          { label: 'Metadata', value: 'METADATA' },
        ],
      },
      defaultValue: 'DATA',
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbFetchDeviceCredentialsNode': [
    {
      field: 'fetchTo',
      label: 'Fetch credentials to',
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Message', value: 'DATA' },
          { label: 'Metadata', value: 'METADATA' },
        ],
      },
      defaultValue: 'DATA',
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetAttributesNode': [
    {
      field: 'clientAttributeNames',
      label: 'Client attributes',
      component: 'Select',
      componentProps: {
        placeholder: 'Add attribute key',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
    },
    {
      field: 'sharedAttributeNames',
      label: 'Shared attributes',
      component: 'Select',
      componentProps: {
        placeholder: 'Add attribute key',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
    },
    {
      field: 'serverAttributeNames',
      label: 'Server attributes',
      component: 'Select',
      componentProps: {
        placeholder: 'Add attribute key',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
    },
    {
      field: 'latestTsKeyNames',
      label: 'Latest telemetry',
      component: 'Select',
      componentProps: {
        placeholder: 'Add telemetry key',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
    },
    {
      field: 'getLatestValueWithTs',
      label: 'Fetch latest telemetry with timestamp',
      component: 'Switch',
      defaultValue: false,
      show: (value) => {
        return value.model.latestTsKeyNames?.length > 0;
      },
    },
    {
      field: 'fetchTo',
      label: 'Add originator attributes to',
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Message', value: 'DATA' },
          { label: 'Metadata', value: 'METADATA' },
        ],
      },
      defaultValue: 'METADATA',
    },
    {
      field: 'tellFailureIfAbsent',
      label: 'Tell failure if any of the attributes are missing',
      component: 'Switch',
      defaultValue: true,
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetOriginatorFieldsNode': [
    {
      field: 'dataMapping',
      label: '',
      component: 'Input',
      componentProps: {
        leftTitle: 'Source attribute key',
        rightTitle: 'Target key',
        isSelect: true,
        selectType: 'org.thingsboard.rule.engine.metadata.TbGetOriginatorFieldsNode',
      },
      slot: 'tableForm',
      colProps: {
        span: 24,
      },
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetTelemetryNode': [
    {
      field: 'latestTsKeyNames',
      label: 'Timeseries keys',
      component: 'Select',
      componentProps: {
        mode: 'tags',
        open: false,
        maxTagCount: 'responsive',
        placeholder: 'Add timeseries key',
      },
      required: true,
    },
    {
      field: 'useMetadataIntervalPatterns',
      label: 'Use dynamic interval',
      component: 'Switch',
      defaultValue: false,
    },
    {
      field: 'startInterval',
      label: 'Interval start',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 2147483647,
      },
      defaultValue: 2,
      required: true,
      show: (value) => !value.model.useMetadataIntervalPatterns,
    },
    {
      field: 'startIntervalTimeUnit',
      label: 'Time unit',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: 'Milliseconds', value: 'MILLISECONDS' },
          { label: 'Seconds', value: 'SECONDS' },
          { label: 'Minutes', value: 'MINUTES' },
          { label: 'Hours', value: 'HOURS' },
          { label: 'Days', value: 'DAYS' },
        ],
      },
      defaultValue: 'MINUTES',
      show: (value) => !value.model.useMetadataIntervalPatterns,
    },
    {
      field: 'endInterval',
      label: 'Interval start',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 2147483647,
      },
      defaultValue: 1,
      required: true,
      show: (value) => !value.model.useMetadataIntervalPatterns,
    },
    {
      field: 'endIntervalTimeUnit',
      label: 'Time unit',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: 'Milliseconds', value: 'MILLISECONDS' },
          { label: 'Seconds', value: 'SECONDS' },
          { label: 'Minutes', value: 'MINUTES' },
          { label: 'Hours', value: 'HOURS' },
          { label: 'Days', value: 'DAYS' },
        ],
      },
      defaultValue: 'MINUTES',
      show: (value) => !value.model.useMetadataIntervalPatterns,
    },
    {
      field: 'startIntervalPattern',
      label: 'Interval start',
      component: 'Input',
      required: true,
      show: (value) => value.model.useMetadataIntervalPatterns,
    },
    {
      field: 'endIntervalPattern',
      label: 'Interval end',
      component: 'Input',
      required: true,
      show: (value) => value.model.useMetadataIntervalPatterns,
    },
    {
      field: 'fetchMode',
      label: 'Fetch strategy',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: 'First', value: 'FIRST' },
          { label: 'Last', value: 'LAST' },
          { label: 'All', value: 'ALL' },
        ],
      },
      defaultValue: 'FIRST',
    },
    {
      field: 'aggregation',
      label: '数据聚合功能',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          {
            label: '最小值',
            value: 'MIN',
          },
          {
            label: '最大值',
            value: 'MAX',
          },
          {
            label: '平均值',
            value: 'AVG',
          },
          {
            label: '求和',
            value: 'SUM',
          },
          {
            label: '计数',
            value: 'COUNT',
          },
          {
            label: '无',
            value: 'NONE',
          },
        ],
      },
      defaultValue: 'NONE',
      show: (value) => value.model.fetchMode === 'ALL',
    },
    {
      field: 'orderBy',
      label: 'Order by timestamp',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: 'Ascending', value: 'ASC' },
          { label: 'Descending', value: 'DESC' },
        ],
      },
      defaultValue: 'ASC',
      show: (value) => value.model.fetchMode === 'ALL',
    },
    {
      field: 'limit',
      label: 'Limit',
      component: 'InputNumber',
      componentProps: {
        min: 2,
        max: 1000,
      },
      required: true,
      show: (value) => value.model.fetchMode === 'ALL',
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetDeviceAttrNode': [
    {
      field: 'deviceRelationsQuery',
      label: '',
      component: 'Input',
      show: false,
    },
    {
      field: 'deviceRelationsQuery.direction',
      label: '方向',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '从originator', value: 'FROM' },
          { label: '到originator', value: 'TO' },
        ],
      },
      defaultValue: 'FROM',
    },
    {
      field: 'deviceRelationsQuery.maxLevel',
      label: 'Max relation level',
      component: 'InputNumber',
      componentProps: {
        min: 1,
      },
      defaultValue: 1,
    },
    {
      field: 'deviceRelationsQuery.fetchLastLevelOnly',
      label: '仅获取最后一级关联',
      component: 'Switch',
      defaultValue: false,
      show: (value) => value.model.deviceRelationsQuery?.maxLevel > 1,
    },
    {
      field: 'deviceRelationsQuery.relationType',
      label: '关联类型',
      component: 'Select',
      componentProps: {
        options: [
          { label: 'Contains', value: 'Contains' },
          { label: 'Manages', value: 'Manages' },
        ],
      },
      defaultValue: 'Contains',
    },
    {
      field: 'deviceRelationsQuery.deviceTypes',
      label: 'Device profiles',
      component: 'ApiSelect',
      componentProps: {
        listHeight: 160,
        maxTagCount: 'responsive',
        api: getDeviceTypes,
        labelField: 'type',
        valueField: 'type',
        immediate: true,
        mode: 'tags',
      },
      defaultValue: ['default'],
    },
    {
      field: 'clientAttributeNames',
      label: 'Client attributes',
      component: 'Select',
      componentProps: {
        placeholder: 'Add attribute key',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
    },
    {
      field: 'sharedAttributeNames',
      label: 'Shared attributes',
      component: 'Select',
      componentProps: {
        placeholder: 'Add attribute key',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
    },
    {
      field: 'serverAttributeNames',
      label: 'Server attributes',
      component: 'Select',
      componentProps: {
        placeholder: 'Add attribute key',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
    },
    {
      field: 'latestTsKeyNames',
      label: 'Latest telemetry',
      component: 'Select',
      componentProps: {
        placeholder: 'Add telemetry key',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
    },
    {
      field: 'getLatestValueWithTs',
      label: 'Fetch latest telemetry with timestamp',
      component: 'Switch',
      defaultValue: false,
      show: (value) => {
        return value.model.latestTsKeyNames?.length > 0;
      },
    },
    {
      field: 'fetchTo',
      label: 'Add originator attributes to',
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Message', value: 'DATA' },
          { label: 'Metadata', value: 'METADATA' },
        ],
      },
      defaultValue: 'METADATA',
    },
    {
      field: 'tellFailureIfAbsent',
      label: 'Tell failure if any of the attributes are missing',
      component: 'Switch',
      defaultValue: true,
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetRelatedAttributeNode': [
    {
      field: 'relationsQuery.direction',
      label: '方向',
      component: 'Select',
      componentProps: {
        options: [
          { label: '从 originator', value: 'FROM' },
          { label: '到 originator', value: 'TO' },
        ],
        allowClear: false,
      },
      defaultValue: 'TO',
      required: true,
    },
    {
      field: 'relationsQuery.maxLevel',
      label: 'Max relation level',
      component: 'InputNumber',
      componentProps: {
        min: 1,
      },
      defaultValue: 1,
      required: true,
    },
    {
      field: 'relationsQuery.filters',
      label: '关联筛选器',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: '关联类型',
        rightTitle: '实体类型',
        isSelect: true,
        selectType: 'org.thingsboard.rule.engine.metadata.TbGetRelatedAttributeNode',
        resultType: 'array',
      },
      colProps: {
        span: 24,
      },
    },
    {
      field: 'dataToFetch',
      label: 'Data to fetch',
      component: 'RadioButtonGroup',
      componentProps: ({ formActionType }) => {
        return {
          options: [
            { label: 'Attributes', value: 'ATTRIBUTES' },
            { label: 'Latest telemetry', value: 'LATEST_TELEMETRY' },
            { label: 'Fields', value: 'FIELDS' },
          ],
          onChange: (value: string) => {
            const { updateSchema } = formActionType;
            let leftTitle = '',
              label = '',
              isSelect = false;
            switch (value) {
              case 'ATTRIBUTES':
                leftTitle = 'Source attribute key';
                label = 'Attributes mapping';
                isSelect = false;
                break;
              case 'LATEST_TELEMETRY':
                leftTitle = 'Source telemetry key';
                label = 'Latest telemetry mapping';
                isSelect = false;
                break;
              case 'FIELDS':
                leftTitle = 'Source field';
                label = 'Fields mapping';
                isSelect = true;
                break;
            }
            updateSchema({
              field: 'dataMapping',
              label,
              componentProps: {
                leftTitle,
                rightTitle: 'Target key',
                isSelect,
                selectType: 'org.thingsboard.rule.engine.metadata.TbGetOriginatorFieldsNode',
                resultType: 'object',
              },
            });
          },
        };
      },
      defaultValue: 'ATTRIBUTES',
      colProps: {
        span: 24,
      },
    },
    {
      field: 'dataMapping',
      label: 'Attributes mapping',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Source attribute key',
        rightTitle: 'Target key',
        isSelect: false,
        selectType: 'org.thingsboard.rule.engine.metadata.TbGetOriginatorFieldsNode',
        resultType: 'object',
      },
      colProps: {
        span: 24,
      },
    },
    {
      field: 'fetchTo',
      label: 'Add selected details to',
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Message', value: 'DATA' },
          { label: 'Metadata', value: 'METADATA' },
        ],
      },
      defaultValue: 'DATA',
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetTenantAttributeNode': [
    {
      field: 'dataToFetch',
      label: "Mapping of customer's",
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Attributes', value: 'ATTRIBUTES' },
          { label: 'Latest telemetry', value: 'LATEST_TELEMETRY' },
        ],
      },
      defaultValue: 'ATTRIBUTES',
      required: true,
      colProps: {
        span: 24,
      },
    },
    {
      field: 'dataMapping',
      label: '',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Source attribute key',
        rightTitle: 'Target key',
      },
      colProps: {
        span: 24,
      },
    },
    {
      field: 'fetchTo',
      label: 'Add mapped latest telemetry to',
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Message', value: 'DATA' },
          { label: 'Metadata', value: 'METADATA' },
        ],
      },
      defaultValue: 'DATA',
    },
  ],
  'org.thingsboard.rule.engine.metadata.TbGetTenantDetailsNode': [
    {
      field: 'fetchTo',
      label: 'Add selected details to',
      component: 'RadioButtonGroup',
      componentProps: {
        options: [
          { label: 'Message', value: 'DATA' },
          { label: 'Metadata', value: 'METADATA' },
        ],
      },
      defaultValue: 'DATA',
    },
  ],
  'org.thingsboard.rule.engine.transform.TbCopyKeysNode': [
    {
      field: 'fromMetadata',
      label: 'Copy from',
      component: 'RadioGroup',
      componentProps: {
        options: [
          {
            label: 'Data to metadata',
            value: false,
          },
          {
            label: 'Metadata to data',
            value: true,
          },
        ],
      },
      defaultValue: false,
    },
    {
      field: 'keys',
      label: 'Keys',
      component: 'Select',
      componentProps: {
        placeholder: 'Keys',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.deduplication.TbMsgDeduplicationNode': [
    {
      field: 'interval',
      label: 'interval',
      component: 'InputNumber',
      componentProps: {
        min: 1,
      },
    },
    {
      field: 'strategy',
      label: 'Strategy',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: 'First', value: 'FIRST' },
          { label: 'Last', value: 'LAST' },
          { label: 'All', value: 'ALL' },
        ],
      },
      defaultValue: 'FIRST',
      required: true,
    },
    {
      field: 'outMsgType',
      label: 'Output message type',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          {
            label: 'POST_TELEMETRY_REQUEST',
            value: 'POST_TELEMETRY_REQUEST',
          },
          {
            label: 'POST_ATTRIBUTES_REQUEST',
            value: 'POST_ATTRIBUTES_REQUEST',
          },
        ],
      },
      defaultValue: null,
      required: true,
      ifShow: (value) => value.model.strategy === 'ALL',
    },
    {
      field: 'queueName',
      label: '队列',
      component: 'ApiSelect',
      componentProps: () => {
        const params = ref({
          pageSize: 10,
          page: 0,
          sortProperty: 'name',
          sortOrder: 'ASC',
          serviceType: 'TB_RULE_ENGINE',
          textSearch: '',
        });
        return {
          api: getQueues,
          params: params.value,
          resultField: 'data',
          labelField: 'name',
          showSearch: true,
          valueField: 'name',
          onSearch: useDebounceFn((e) => {
            params.value.textSearch = e;
          }, 300),
          immediate: true,
        };
      },
      required: true,
      ifShow: (value) => value.model.strategy === 'ALL',
    },
    {
      field: 'maxPendingMsgs',
      label: 'Max pending messages',
      component: 'InputNumber',
      componentProps: { min: 1, max: 1000 },
      defaultValue: 1000,
      required: true,
    },
    {
      field: 'maxRetries',
      label: 'Max retries',
      component: 'InputNumber',
      componentProps: { min: 0, max: 100 },
      defaultValue: 3,
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.transform.TbDeleteKeysNode': [
    {
      field: 'fromMetadata',
      label: 'Copy from',
      component: 'RadioGroup',
      componentProps: {
        options: [
          {
            label: 'Data to metadata',
            value: false,
          },
          {
            label: 'Metadata to data',
            value: true,
          },
        ],
      },
      defaultValue: false,
    },
    {
      field: 'keys',
      label: 'Keys',
      component: 'Select',
      componentProps: {
        placeholder: 'Keys',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.transform.TbJsonPathNode': [
    {
      field: 'jsonPath',
      label: 'JSON path expression',
      component: 'Input',
      defaultValue: '$',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.transform.TbRenameKeysNode': [
    {
      field: 'fromMetadata',
      label: 'Rename keys in',
      component: 'RadioGroup',
      componentProps: {
        options: [
          { label: 'Data', value: false },
          { label: 'Metadata', value: true },
        ],
      },
      defaultValue: false,
    },
    {
      field: 'renameKeysMapping',
      label: '',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Key name',
        rightTitle: 'New key name',
      },
      colProps: {
        span: 24,
      },
    },
  ],
  'org.thingsboard.rule.engine.transform.TbTransformMsgNode': [
    {
      field: 'scriptLang',
      label: '',
      component: 'RadioButtonGroup',
      slot: 'scriptLangSlot',
      componentProps: {
        options: [
          {
            label: 'TBEL',
            value: 'TBEL',
          },
          {
            label: 'JavaScript',
            value: 'JS',
          },
        ],
      },
      colProps: {
        span: 24,
      },
      defaultValue: 'TBEL',
    },
    {
      field: 'tbelScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: 'return {msg: msg, metadata: metadata, msgType: msgType};',
    },
    {
      field: 'jsScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: 'return {msg: msg, metadata: metadata, msgType: msgType};',
    },
  ],
  'org.thingsboard.rule.engine.mail.TbMsgToEmailNode': [
    {
      field: 'fromTemplate',
      label: 'From Template',
      component: 'InputTextArea',
      required: true,
      defaultValue: 'info@testmail.org',
    },
    {
      field: 'toTemplate',
      label: 'To Template',
      component: 'InputTextArea',
      required: true,
      defaultValue: '${userEmail}',
    },
    {
      field: 'ccTemplate',
      label: 'Cc Template',
      component: 'InputTextArea',
    },
    {
      field: 'bccTemplate',
      label: 'Bcc Template',
      component: 'InputTextArea',
    },
    {
      field: 'bccTemplate',
      label: 'Subject Template',
      component: 'InputTextArea',
      required: true,
      defaultValue: 'Device ${deviceType} temperature high',
    },
    {
      field: 'mailBodyType',
      label: 'Mail body type',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          {
            label: 'Plain Text',
            value: 'false',
          },
          {
            label: 'HTML',
            value: 'true',
          },
          {
            label: 'Dynamic',
            value: 'dynamic',
          },
        ],
      },
      defaultValue: 'false',
    },
    {
      field: 'isHtmlTemplate',
      label: 'Dynamic mail body type',
      component: 'Input',
      required: true,
      ifShow: (value) => value.model.mailBodyType === 'dynamic',
    },
    {
      field: 'bodyTemplate',
      label: 'Body Template',
      component: 'InputTextArea',
      defaultValue: 'Device ${deviceName} has high temperature ${temp}',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.action.TbAssignToCustomerNode': [
    {
      field: 'customerNamePattern',
      label: 'Customer name pattern',
      component: 'Input',
      required: true,
    },
    {
      field: 'createCustomerIfNotExists',
      label: 'Create new customer if not exists',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'customerCacheExpiration',
      label: 'Customers cache expiration time (sec)',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      required: true,
      defaultValue: 300,
    },
  ],
  'org.thingsboard.rule.engine.action.TbClearAlarmNode': [
    {
      field: 'scriptLang',
      label: '',
      component: 'RadioButtonGroup',
      slot: 'scriptLangSlot',
      componentProps: {
        options: [
          {
            label: 'TBEL',
            value: 'TBEL',
          },
          {
            label: 'JavaScript',
            value: 'JS',
          },
        ],
      },
      colProps: {
        span: 24,
      },
      defaultValue: 'TBEL',
    },
    {
      field: 'tbelScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `var details = {};
if (metadata.prevAlarmDetails != null) {
    details = JSON.parse(metadata.prevAlarmDetails);
    //remove prevAlarmDetails from metadata
    metadata.remove('prevAlarmDetails');
    //now metadata is the same as it comes IN this rule node
}


return details;`,
    },
    {
      field: 'jsScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `var details = {};
if (metadata.prevAlarmDetails) {
    details = JSON.parse(metadata.prevAlarmDetails);
    //remove prevAlarmDetails from metadata
    delete metadata.prevAlarmDetails;
    //now metadata is the same as it comes IN this rule node
}


return details;`,
    },
    {
      field: 'alarmType',
      label: 'Alarm type',
      component: 'Input',
      defaultValue: 'General Alarm',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.action.TbCreateAlarmNode': [
    {
      field: 'useMessageAlarmData',
      label: 'Use message alarm data',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'overwriteAlarmDetails',
      label: 'Overwrite alarm details',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => model.useMessageAlarmData,
    },
    {
      field: 'scriptLang',
      label: '',
      component: 'RadioButtonGroup',
      slot: 'scriptLangSlot',
      componentProps: {
        options: [
          {
            label: 'TBEL',
            value: 'TBEL',
          },
          {
            label: 'JavaScript',
            value: 'JS',
          },
        ],
      },
      colProps: {
        span: 24,
      },
      defaultValue: 'TBEL',
      show: ({ model }) => model.overwriteAlarmDetails || !model.useMessageAlarmData,
    },
    {
      field: 'tbelScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `var details = {};
if (metadata.prevAlarmDetails != null) {
    details = JSON.parse(metadata.prevAlarmDetails);
    //remove prevAlarmDetails from metadata
    metadata.remove('prevAlarmDetails');
    //now metadata is the same as it comes IN this rule node
}


return details;`,
    },
    {
      field: 'jsScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `var details = {};
if (metadata.prevAlarmDetails) {
    details = JSON.parse(metadata.prevAlarmDetails);
    //remove prevAlarmDetails from metadata
    delete metadata.prevAlarmDetails;
    //now metadata is the same as it comes IN this rule node
}


return details;`,
    },
    {
      field: 'alarmType',
      label: 'Alarm type',
      component: 'Input',
      required: true,
      defaultValue: 'General Alarm',
      show: ({ model }) => !model.useMessageAlarmData,
    },
    {
      field: 'dynamicSeverity',
      label: 'Use alarm severity pattern',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => !model.useMessageAlarmData,
    },
    {
      field: 'severity',
      label: 'Alarm severity',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '危险', value: 'CRITICAL' },
          { label: '重要', value: 'MAJOR' },
          { label: '次要', value: 'MINOR' },
          { label: '警告', value: 'WARNING' },
          { label: '不确定', value: 'INDETERMINATE' },
        ],
      },
      defaultValue: 'CRITICAL',
      required: true,
      ifShow: ({ model }) => !model.dynamicSeverity,
      show: ({ model }) => !model.useMessageAlarmData,
    },
    {
      field: 'severity',
      label: 'Alarm severity pattern',
      component: 'Input',
      required: true,
      ifShow: ({ model }) => model.dynamicSeverity,
      show: ({ model }) => !model.useMessageAlarmData,
    },
    {
      field: 'propagate',
      label: 'Propagate alarm to related entities',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => !model.useMessageAlarmData,
    },
    {
      field: 'relationTypes',
      label: 'Relation types to propagate',
      component: 'Select',
      componentProps: {
        placeholder: '请输入',
        mode: 'tags',
        maxTagCount: 'responsive',
        open: false,
      },
      show: ({ model }) => model.propagate && !model.useMessageAlarmData,
    },
    {
      field: 'propagateToOwner',
      label: 'Propagate alarm to entity owner (Customer or Tenant)',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => !model.useMessageAlarmData,
    },
    {
      field: 'propagateToTenant',
      label: 'Propagate alarm to Tenant',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => !model.useMessageAlarmData,
    },
  ],
  'org.thingsboard.rule.engine.action.TbCreateRelationNode': [
    {
      field: 'direction',
      label: '方向',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '从', value: 'FROM' },
          { label: '到', value: 'TO' },
        ],
      },
      defaultValue: 'FROM',
      required: true,
    },
    {
      field: 'entityType',
      label: '实体类型',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '设备', value: 'DEVICE' },
          { label: '资产', value: 'ASSET' },
          { label: '实体视图', value: 'ENTITY_VIEW' },
          { label: '租户', value: 'TENANT' },
          { label: '客户', value: 'CUSTOMER' },
          { label: '用户', value: 'USER' },
          { label: '仪表盘', value: 'DASHBOARD' },
          { label: '边缘', value: 'EDGE' },
        ],
      },
      required: true,
    },
    {
      field: 'entityNamePattern',
      label: 'Name pattern',
      component: 'Input',
      required: true,
    },
    {
      field: 'entityTypePattern',
      label: 'Type pattern',
      component: 'Input',
      required: true,
      show: ({ model }) => model.entityType === 'DEVICE' || model.entityType === 'ASSET',
    },
    {
      field: 'relationType',
      label: 'Relation type pattern',
      component: 'Input',
      defaultValue: 'Contains',
      required: true,
    },
    {
      field: 'createEntityIfNotExists',
      label: 'Create new entity if not exists',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) =>
        model.entityType === 'DEVICE' ||
        model.entityType === 'ASSET' ||
        model.entityType === 'CUSTOMER',
    },
    {
      field: 'removeCurrentRelations',
      label: 'Remove current relations',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'changeOriginatorToRelatedEntity',
      label: 'Change originator to related entity',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'entityCacheExpiration',
      label: 'Entities cache expiration time (sec)',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 300,
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.delay.TbMsgDelayNode': [
    {
      field: 'useMetadataPeriodInSecondsPatterns',
      label: 'Use period in seconds pattern',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'periodInSeconds',
      label: 'Period in seconds',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 60,
      show: ({ model }) => !model.useMetadataPeriodInSecondsPatterns,
      required: true,
    },
    {
      field: 'periodInSecondsPattern',
      label: 'Period in seconds',
      component: 'Input',
      show: ({ model }) => model.useMetadataPeriodInSecondsPatterns,
      required: true,
    },
    {
      field: 'maxPendingMsgs',
      label: 'Maximum pending messages',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 100000,
      },
      defaultValue: 1000,
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.telemetry.TbMsgDeleteAttributesNode': [
    {
      field: 'scope',
      label: '设备属性范围',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '客户端属性', value: 'CLIENT_SCOPE' },
          { label: '服务端属性', value: 'SERVER_SCOPE' },
          { label: '共享属性', value: 'SHARED_SCOPE' },
        ],
      },
      defaultValue: 'CLIENT_SCOPE',
      required: true,
    },
    {
      field: 'keys',
      label: '属性键',
      component: 'Select',
      componentProps: {
        mode: 'tags',
        open: false,
      },
      required: true,
    },
    {
      field: 'sendAttributesDeletedNotification',
      label: 'Send attributes deleted notification',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'notifyDevice',
      label: 'Notify device',
      component: 'Checkbox',
      ifShow: ({ model }) => model.scope === 'SHARED_SCOPE',
    },
  ],
  'org.thingsboard.rule.engine.action.TbDeleteRelationNode': [
    {
      field: 'deleteForSingleEntity',
      label: 'Delete relation to specific entity',
      component: 'Checkbox',
      defaultValue: true,
    },
    {
      field: 'direction',
      label: '方向',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '从', value: 'FROM' },
          { label: '到', value: 'TO' },
        ],
      },
      defaultValue: 'FROM',
      required: true,
    },
    {
      field: 'entityType',
      label: '实体类型',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '设备', value: 'DEVICE' },
          { label: '资产', value: 'ASSET' },
          { label: '实体视图', value: 'ENTITY_VIEW' },
          { label: '租户', value: 'TENANT' },
          { label: '客户', value: 'CUSTOMER' },
          { label: '用户', value: 'USER' },
          { label: '仪表盘', value: 'DASHBOARD' },
          { label: '边缘', value: 'EDGE' },
        ],
      },
      required: true,
      show: ({ model }) => model.deleteForSingleEntity,
    },
    {
      field: 'entityNamePattern',
      label: 'Name pattern',
      component: 'Input',
      required: true,
      show: ({ model }) => model.deleteForSingleEntity,
    },
    {
      field: 'relationType',
      label: 'Relation type pattern',
      component: 'Input',
      defaultValue: 'Contains',
      required: true,
    },
    {
      field: 'entityCacheExpiration',
      label: 'Entities cache expiration time (sec)',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 3000,
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.profile.TbDeviceProfileNode': [
    {
      field: 'persistAlarmRulesState',
      label: 'Persist state of alarm rules',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'fetchAlarmRulesStateOnStart',
      label: 'Fetch state of alarm rules',
      component: 'Checkbox',
      defaultValue: false,
    },
  ],
  'org.thingsboard.rule.engine.debug.TbMsgGeneratorNode': [
    {
      field: 'msgCount',
      label: 'Message count (0 - unlimited)',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      required: true,
      defaultValue: 0,
    },
    {
      field: 'periodInSeconds',
      label: 'Period in seconds',
      component: 'InputNumber',
      componentProps: {
        min: 1,
      },
      required: true,
      defaultValue: 1,
    },
    {
      field: 'originatorType',
      label: '实体类型',
      component: 'Select',
      componentProps: ({ formModel, formActionType }) => {
        return {
          allowClear: false,
          listHeight: 160,
          options: [
            { label: '设备', value: 'DEVICE' },
            { label: '资产', value: 'ASSET' },
            { label: '实体视图', value: 'ENTITY_VIEW' },
            { label: '租户', value: 'TENANT' },
            { label: '客户', value: 'CUSTOMER' },
            { label: '用户', value: 'USER' },
            { label: '仪表盘', value: 'DASHBOARD' },
            { label: '边缘', value: 'EDGE' },
          ],
          onChange: async (value: string) => {
            formModel.originatorId = undefined;
            const { updateSchema } = formActionType;
            updateSchema({
              field: 'originatorId',
              componentProps: {
                api: Apis[value].api,
                params: Apis[value].params,
                ...(value === 'TENANT'
                  ? {
                      resultField: '',
                    }
                  : {}),
              },
            });
          },
        };
      },
    },
    {
      field: 'originatorId',
      label: '实体ID',
      component: 'ApiSelect',
      componentProps: {
        resultField: 'data',
        labelField: 'name',
        valueField: 'id.id',
        showSearch: true,
        immediate: false,
        listHeight: 160,
      },
      ifShow: ({ model }) => model.originatorType,
    },
    {
      field: 'queueName',
      label: '队列',
      component: 'ApiSelect',
      componentProps: () => {
        const params = ref({
          pageSize: 10,
          page: 0,
          sortProperty: 'name',
          sortOrder: 'ASC',
          serviceType: 'TB_RULE_ENGINE',
          textSearch: '',
        });
        return {
          api: getQueues,
          params: params.value,
          resultField: 'data',
          labelField: 'name',
          showSearch: true,
          valueField: 'name',
          onSearch: useDebounceFn((e) => {
            params.value.textSearch = e;
          }, 300),
          immediate: true,
        };
      },
    },
    {
      field: 'scriptLang',
      label: '',
      component: 'RadioButtonGroup',
      slot: 'scriptLangSlot',
      componentProps: {
        options: [
          {
            label: 'TBEL',
            value: 'TBEL',
          },
          {
            label: 'JavaScript',
            value: 'JS',
          },
        ],
      },
      colProps: {
        span: 24,
      },
      defaultValue: 'TBEL',
    },
    {
      field: 'tbelScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `var msg = { temp: 42, humidity: 77 };
var metadata = { data: 40 };
var msgType = "POST_TELEMETRY_REQUEST";

return { msg: msg, metadata: metadata, msgType: msgType };`,
    },
    {
      field: 'jsScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `var msg = { temp: 42, humidity: 77 };
var metadata = { data: 40 };
var msgType = "POST_TELEMETRY_REQUEST";

return { msg: msg, metadata: metadata, msgType: msgType };`,
    },
  ],
  'org.thingsboard.rule.engine.geo.TbGpsGeofencingActionNode': [
    {
      field: 'latitudeKeyName',
      label: 'tb.rulenode.latitude-key-name',
      component: 'Input',
      required: true,
      defaultValue: 'latitude',
    },
    {
      field: 'longitudeKeyName',
      label: 'tb.rulenode.latitude-key-name',
      component: 'Input',
      required: true,
      defaultValue: 'longitude',
    },
    {
      field: 'perimeterType',
      label: 'Perimeter type',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Circle',
            value: 'CIRCLE',
          },
          {
            label: 'Polygon',
            value: 'POLYGON',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'POLYGON',
      required: true,
    },
    {
      field: 'fetchPerimeterInfoFromMessageMetadata',
      label: 'Fetch perimeter information from metadata',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'polygonsDefinition',
      label: 'polygonsDefinition',
      component: 'Input',
      required: true,
      show: ({ model }) =>
        !model.fetchPerimeterInfoFromMessageMetadata && model.perimeterType === 'POLYGON',
    },
    {
      field: 'perimeterKeyName',
      label: 'Perimeter key name',
      component: 'Input',
      required: true,
      show: ({ model }) => model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'centerLatitude',
      label: 'Center latitude',
      component: 'InputNumber',
      componentProps: {
        min: -90,
        max: 90,
        step: 0.1,
      },
      required: true,
      show: ({ model }) =>
        model.perimeterType === 'CIRCLE' && !model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'centerLongitude',
      label: 'Center longitude',
      component: 'InputNumber',
      componentProps: {
        min: -90,
        max: 90,
        step: 0.1,
      },
      required: true,
      show: ({ model }) =>
        model.perimeterType === 'CIRCLE' && !model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'range',
      label: 'Range',
      component: 'InputNumber',
      componentProps: {
        min: 0,
        step: 0.1,
      },
      required: true,
      show: ({ model }) =>
        model.perimeterType === 'CIRCLE' && !model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'rangeUnit',
      label: 'Range unit',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Meter',
            value: 'METER',
          },
          {
            label: 'Kilometer',
            value: 'KILOMETER',
          },
          {
            label: 'Foot',
            value: 'FOOT',
          },
          {
            label: 'Mile',
            value: 'MILE',
          },
          {
            label: 'Nautical mile',
            value: 'NAUTICAL_MILE',
          },
        ],
      },
      defaultValue: 'METER',
      show: ({ model }) =>
        model.perimeterType === 'CIRCLE' && !model.fetchPerimeterInfoFromMessageMetadata,
    },
    {
      field: 'minInsideDuration',
      label: 'Minimal inside duration',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 2147483647,
      },
      defaultValue: 1,
      required: true,
    },
    {
      field: 'minInsideDurationTimeUnit',
      label: 'Minimal inside duration time unit',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Milliseconds',
            value: 'MILLISECONDS',
          },
          {
            label: 'Seconds',
            value: 'SECONDS',
          },
          {
            label: 'Minutes',
            value: 'MINUTES',
          },
          {
            label: 'Hours',
            value: 'HOURS',
          },
          {
            label: 'Days',
            value: 'DAYS',
          },
        ],
      },
      defaultValue: 'SECONDS',
      required: true,
    },
    {
      field: 'minOutsideDuration',
      label: 'Minimal outside duration',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 2147483647,
      },
      defaultValue: 1,
      required: true,
    },
    {
      field: 'minOutsideDurationTimeUnit',
      label: 'Minimal outside duration time unit',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Milliseconds',
            value: 'MILLISECONDS',
          },
          {
            label: 'Seconds',
            value: 'SECONDS',
          },
          {
            label: 'Minutes',
            value: 'MINUTES',
          },
          {
            label: 'Hours',
            value: 'HOURS',
          },
          {
            label: 'Days',
            value: 'DAYS',
          },
        ],
      },
      defaultValue: 'SECONDS',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.action.TbLogNode': [
    {
      field: 'scriptLang',
      label: '',
      component: 'RadioButtonGroup',
      slot: 'scriptLangSlot',
      componentProps: {
        options: [
          {
            label: 'TBEL',
            value: 'TBEL',
          },
          {
            label: 'JavaScript',
            value: 'JS',
          },
        ],
      },
      colProps: {
        span: 24,
      },
      defaultValue: 'TBEL',
    },
    {
      field: 'tbelScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `return '\nIncoming message:\n' + JSON.stringify(msg) + '\nIncoming metadata:\n' + JSON.stringify(metadata);`,
    },
    {
      field: 'jsScript',
      label: '',
      component: 'Input',
      show: false,
      defaultValue: `return '\nIncoming message:\n' + JSON.stringify(msg) + '\nIncoming metadata:\n' + JSON.stringify(metadata);`,
    },
  ],
  'org.thingsboard.rule.engine.action.TbMsgCountNode': [
    {
      field: 'interval',
      label: 'Interval in seconds',
      component: 'InputNumber',
      componentProps: {
        min: 1,
      },
      defaultValue: 1,
      required: true,
    },
    {
      field: 'telemetryPrefix',
      label: 'Output timeseries key prefix',
      component: 'Input',
      defaultValue: 'messageCount',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.edge.TbMsgPushToEdgeNode': [
    {
      field: 'scope',
      label: '设备属性范围',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '客户端属性', value: 'CLIENT_SCOPE' },
          { label: '服务端属性', value: 'SERVER_SCOPE' },
          { label: '共享属性', value: 'SHARED_SCOPE' },
        ],
      },
      defaultValue: 'CLIENT_SCOPE',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.rpc.TbSendRPCReplyNode': [
    {
      field: 'requestIdMetaDataAttribute',
      label: 'Request Id Metadata attribute name',
      component: 'Input',
      defaultValue: 'requestId',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode': [
    {
      field: 'timeoutInSeconds',
      label: 'Timeout in seconds',
      component: 'InputNumber',
      componentProps: { min: 1 },
      defaultValue: 60,
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode': [
    {
      field: 'scope',
      label: '设备属性范围',
      component: 'Select',
      componentProps: {
        allowClear: false,
        options: [
          { label: '客户端属性', value: 'CLIENT_SCOPE' },
          { label: '服务端属性', value: 'SERVER_SCOPE' },
          { label: '共享属性', value: 'SHARED_SCOPE' },
        ],
      },
      defaultValue: 'CLIENT_SCOPE',
      required: true,
    },
    {
      field: 'updateAttributesOnlyOnValueChange',
      label: 'Save attributes only if the value changes',
      component: 'Switch',
      defaultValue: false,
    },
    {
      field: 'sendAttributesUpdatedNotification',
      label: 'Send attributes updated notification',
      component: 'Switch',
      defaultValue: false,
      ifShow: ({ model }) => model.scope === 'SERVER_SCOPE' || model.scope === 'SHARED_SCOPE',
    },
    {
      field: 'notifyDevice',
      label: 'Notify device',
      component: 'Switch',
      defaultValue: false,
      ifShow: ({ model }) => model.scope === 'SHARED_SCOPE',
    },
  ],
  'org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode': [
    {
      field: 'defaultTTL',
      label: 'Default TTL in seconds',
      component: 'InputNumber',
      componentProps: { min: 0 },
      defaultValue: 1,
      required: true,
    },
    {
      field: 'skipLatestPersistence',
      label: 'Skip latest persistence',
      component: 'Switch',
      defaultValue: false,
    },
    {
      field: 'useServerTs',
      label: 'Use server ts',
      component: 'Switch',
      defaultValue: false,
    },
  ],
  'org.thingsboard.rule.engine.action.TbUnassignFromCustomerNode': [
    {
      field: 'customerNamePattern',
      label: 'Customer name pattern',
      component: 'Input',
      required: true,
    },
    {
      field: 'customerCacheExpiration',
      label: 'Customers cache expiration time (sec)',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 300,
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.aws.sns.TbSnsNode': [
    {
      field: 'topicArnPattern',
      label: 'Topic ARN pattern',
      component: 'Input',
      defaultValue: 'arn:aws:sns:us-east-1:123456789012:MyNewTopic',
      required: true,
    },
    {
      field: 'accessKeyId',
      label: 'AWS Access Key ID',
      component: 'Input',
      required: true,
    },
    {
      field: 'secretAccessKey',
      label: 'AWS Secret Access Key',
      component: 'Input',
      required: true,
    },
    {
      field: 'region',
      label: 'AWS Region',
      component: 'Input',
      defaultValue: 'us-east-1',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.aws.sqs.TbSqsNode': [
    {
      field: 'queueType',
      label: 'Queue type',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Standard',
            value: 'STANDARD',
          },
          {
            label: 'FIFO',
            value: 'FIFO',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'STANDARD',
      required: true,
    },
    {
      field: 'queueUrlPattern',
      label: 'Queue URL pattern',
      component: 'Input',
      defaultValue: 'https://sqs.us-east-1.amazonaws.com/123456789012/my-queue-name',
      required: true,
    },
    {
      field: 'delaySeconds',
      label: 'Delay seconds',
      component: 'InputNumber',
      componentProps: {
        min: 0,
        max: 900,
      },
      required: true,
      show: ({ model }) => model.queueType === 'STANDARD',
    },
    {
      field: 'messageAttributes',
      label: 'Message attributes',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Name',
        rightTitle: 'Value',
      },
      colProps: {
        span: 24,
      },
    },
    {
      field: 'accessKeyId',
      label: 'AWS Access Key ID',
      component: 'Input',
      required: true,
    },
    {
      field: 'secretAccessKey',
      label: 'AWS Secret Access Key',
      component: 'Input',
      required: true,
    },
    {
      field: 'region',
      label: 'AWS Region',
      component: 'Input',
      defaultValue: 'us-east-1',
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.mqtt.azure.TbAzureIotHubNode': [
    {
      field: 'topicPattern',
      label: 'Topic',
      component: 'Input',
      defaultValue: 'devices/<device_id>/messages/events/',
      required: true,
    },
    {
      field: 'host',
      label: 'Hostname',
      component: 'Input',
      defaultValue: '<iot-hub-name>.azure-devices.net',
      required: true,
    },
    {
      field: 'clientId',
      label: 'Device ID',
      component: 'Input',
      required: true,
    },
    {
      field: 'credentials.type',
      label: 'Credentials type',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Shared Access Signature',
            value: 'sas',
          },
          {
            label: 'PEM',
            value: 'cert.PEM',
          },
        ],
      },
      defaultValue: 'sas',
    },
    {
      field: 'credentials.sasKey',
      label: 'SAS Key',
      component: 'InputPassword',
      ifShow: ({ model }) => model['credentials.type'] === 'sas',
    },
    {
      field: 'credentials.caCert',
      label: 'CA certificate file',
      component: 'Upload',
      slot: 'upload',
    },
    {
      field: 'credentials.caCertFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
    },
    {
      field: 'credentials.cert',
      label: 'CA certificate file',
      component: 'Upload',
      slot: 'upload',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.certFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
    },
    {
      field: 'credentials.privateKey',
      label: 'CA certificate file',
      component: 'Upload',
      slot: 'upload',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.privateKeyFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
    },
    {
      field: 'password',
      label: 'Private key password',
      component: 'InputPassword',
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
  ],
  'org.thingsboard.rule.engine.gcp.pubsub.TbPubSubNode': [
    {
      field: 'projectId',
      label: 'GCP project ID',
      component: 'Input',
      defaultValue: 'my-google-cloud-project-id',
      required: true,
    },
    {
      field: 'topicName',
      label: 'Topic name',
      component: 'Input',
      defaultValue: 'my-pubsub-topic-name',
      required: true,
    },
    {
      field: 'serviceAccountKey',
      label: '',
      component: 'Upload',
      slot: 'upload',
      required: true,
    },
    {
      field: 'serviceAccountKeyFileName',
      label: 'GCP service account key file',
      component: 'Upload',
      required: true,
      show: false,
    },
    {
      field: 'messageAttributes',
      label: 'Message attributes',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Name',
        rightTitle: 'Value',
      },
      colProps: {
        span: 24,
      },
    },
  ],
  'org.thingsboard.rule.engine.kafka.TbKafkaNode': [
    {
      field: 'topicPattern',
      label: 'Topic pattern',
      component: 'Input',
      defaultValue: 'my-topic',
      required: true,
    },
    {
      field: 'keyPattern',
      label: 'Key pattern',
      component: 'Input',
    },
    {
      field: 'bootstrapServers',
      label: 'Bootstrap servers',
      component: 'Input',
      defaultValue: 'localhost:9092',
      required: true,
    },
    {
      field: 'retries',
      label: 'Automatically retry times if fails',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 0,
    },
    {
      field: 'batchSize',
      label: 'Produces batch size in bytes',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 16383,
    },
    {
      field: 'linger',
      label: 'Time to buffer locally (ms)',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 0,
    },
    {
      field: 'bufferMemory',
      label: 'Client buffer max size in bytes',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 33554432,
    },
    {
      field: 'acks',
      label: 'Number of acknowledgments',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'all',
            value: 'all',
          },
          {
            label: '-1',
            value: '-1',
          },
          {
            label: '0',
            value: '0',
          },
          {
            label: '1',
            value: '1',
          },
        ],
        allowClear: false,
      },
      defaultValue: '-1',
      required: true,
    },
    {
      field: 'keySerializer',
      label: 'Key serializer',
      component: 'Input',
      defaultValue: 'org.apache.kafka.common.serialization.StringSerializer',
      required: true,
    },
    {
      field: 'valueSerializer',
      label: 'Value serializer',
      component: 'Input',
      defaultValue: 'org.apache.kafka.common.serialization.StringSerializer',
      required: true,
    },
    {
      field: 'otherProperties',
      label: '',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Key',
        rightTitle: 'Value',
      },
      colProps: {
        span: 24,
      },
    },
    {
      field: 'addMetadataKeyValuesAsKafkaHeaders',
      label: 'Add Message metadata key-value pairs to Kafka record headers',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'kafkaHeadersCharset',
      label: 'Charset encoding',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'US-ASCII',
            value: 'US-ASCII',
          },
          {
            label: 'ISO-8859-1',
            value: 'ISO-8859-1',
          },
          {
            label: 'UTF-8',
            value: 'UTF-8',
          },
          {
            label: 'UTF-16BE',
            value: 'UTF-16BE',
          },
          {
            label: 'UTF-16LE',
            value: 'UTF-16LE',
          },
          {
            label: 'UTF-16',
            value: 'UTF-16',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'UTF-8',
      required: true,
      show: ({ model }) => model.addMetadataKeyValuesAsKafkaHeaders,
    },
  ],
  'org.thingsboard.rule.engine.mqtt.TbMqttNode': [
    {
      field: 'topicPattern',
      label: 'Topic pattern',
      component: 'Input',
      defaultValue: 'my-topic',
      required: true,
    },
    {
      field: 'host',
      label: 'Host',
      component: 'Input',
      required: true,
    },
    {
      field: 'port',
      label: 'Port',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 65535,
      },
      defaultValue: 1883,
      required: true,
    },
    {
      field: 'connectTimeoutSec',
      label: 'Connection timeout (sec)',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 200,
      },
      defaultValue: 10,
      required: true,
    },
    {
      field: 'clientId',
      label: 'Client ID',
      component: 'Input',
    },
    {
      field: 'appendClientIdSuffix',
      label: 'Add Service ID as suffix to Client ID',
      component: 'Checkbox',
      defaultValue: false,
      ifShow: ({ model }) => model.clientId,
    },
    {
      field: 'cleanSession',
      label: 'Clean session',
      component: 'Checkbox',
      defaultValue: true,
    },
    {
      field: 'retainedMessage',
      label: 'Retained',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'ssl',
      label: 'Enable SSL',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'credentials.type',
      label: 'Credentials type',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Anonymous',
            value: 'anonymous',
          },
          {
            label: 'Basic',
            value: 'basic',
          },
          {
            label: 'PEM',
            value: 'cert.PEM',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'anonymous',
    },
    {
      field: 'credentials.username',
      label: 'username',
      component: 'Input',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'basic',
    },
    {
      field: 'credentials.password',
      label: 'password',
      component: 'InputPassword',
      ifShow: ({ model }) => model['credentials.type'] === 'basic',
    },
    {
      field: 'credentials.caCert',
      label: 'Server CA certificate file',
      component: 'Upload',
      slot: 'upload',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.cert',
      label: 'Client certificate file',
      component: 'Upload',
      slot: 'upload',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.privateKey',
      label: 'Client private key file',
      component: 'Upload',
      slot: 'upload',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.caCertFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.certFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.privateKeyFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.password',
      label: 'Private key password',
      component: 'InputPassword',
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
  ],
  'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode': [
    {
      field: 'exchangeNamePattern',
      label: 'Exchange name pattern',
      component: 'Input',
    },
    {
      field: 'routingKeyPattern',
      label: 'Routing key pattern',
      component: 'Input',
    },
    {
      field: 'messageProperties',
      label: 'Message properties',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'BASIC',
            value: 'BASIC',
          },
        ],
      },
    },
    {
      field: 'host',
      label: 'Host',
      component: 'Input',
      defaultValue: 'localhost',
      required: true,
    },
    {
      field: 'port',
      label: 'Port',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 65535,
      },
      defaultValue: 5672,
      required: true,
    },
    {
      field: 'virtualHost',
      label: 'virtual host',
      component: 'Input',
      defaultValue: '/',
    },
    {
      field: 'username',
      label: 'Username',
      component: 'Input',
      defaultValue: 'guest',
    },
    {
      field: 'password',
      label: 'Password',
      component: 'InputPassword',
      defaultValue: 'guest',
      required: true,
    },
    {
      field: 'automaticRecoveryEnabled',
      label: 'Automatic recovery',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'connectionTimeout',
      label: 'Connection timeout (ms)',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 60000,
    },
    {
      field: 'handshakeTimeout',
      label: 'Handshake timeout (ms)',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 10000,
    },
    {
      field: 'clientProperties',
      label: 'Client properties',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Key',
        rightTitle: 'Value',
      },
      colProps: {
        span: 24,
      },
    },
  ],
  'org.thingsboard.rule.engine.rest.TbRestApiCallNode': [
    {
      field: 'restEndpointUrlPattern',
      label: 'Endpoint URL pattern',
      component: 'Input',
      defaultValue: 'http://localhost/api',
      required: true,
    },
    {
      field: 'requestMethod',
      label: 'Request method',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'GET',
            value: 'GET',
          },
          {
            label: 'POST',
            value: 'POST',
          },
          {
            label: 'PUT',
            value: 'PUT',
          },
          {
            label: 'DELETE',
            value: 'DELETE',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'POST',
      required: true,
    },
    {
      field: 'enableProxy',
      label: 'Enable proxy',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'useSimpleClientHttpFactory',
      label: 'Use simple client HTTP factory',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => !model.enableProxy,
    },
    {
      field: 'parseToPlainText',
      label: 'Parse to plain text',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'ignoreRequestBody',
      label: 'Without request body',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'useSystemProxyProperties',
      label: 'Use system proxy properties',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => model.enableProxy,
    },
    {
      field: 'readTimeoutMs',
      label: 'Read timeout in millis',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 0,
      show: ({ model }) =>
        !model.useSimpleClientHttpFactory ||
        (model.useSimpleClientHttpFactory && model.enableProxy),
    },
    {
      field: 'maxParallelRequestsCount',
      label: 'Max number of parallel requests',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      defaultValue: 0,
    },
    {
      field: 'proxyScheme',
      label: 'Proxy scheme',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'HTTP',
            value: 'http',
          },
          {
            label: 'HTTPS',
            value: 'https',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'http',
      show: ({ model }) => model.enableProxy && !model.useSystemProxyProperties,
    },
    {
      field: 'proxyHost',
      label: 'Proxy host',
      component: 'Input',
      required: true,
      show: ({ model }) => model.enableProxy && !model.useSystemProxyProperties,
    },
    {
      field: 'proxyPort',
      label: 'Proxy port',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 65535,
      },
      required: true,
      show: ({ model }) => model.enableProxy && !model.useSystemProxyProperties,
    },
    {
      field: 'proxyUser',
      label: 'Proxy user',
      component: 'Input',
      show: ({ model }) => model.enableProxy && !model.useSystemProxyProperties,
    },
    {
      field: 'proxyPassword',
      label: 'Proxy password',
      component: 'Input',
      show: ({ model }) => model.enableProxy && !model.useSystemProxyProperties,
    },
    {
      field: 'dataMapping',
      label: 'Headers',
      component: 'Input',
      slot: 'tableForm',
      componentProps: {
        leftTitle: 'Header',
        rightTitle: 'Value',
      },
      colProps: {
        span: 24,
      },
    },
    {
      field: 'useRedisQueueForMsgPersistence',
      label: 'Use redis queue for message persistence',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'trimQueue',
      label: 'Trim redis queue',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => model.useRedisQueueForMsgPersistence,
    },
    {
      field: 'maxQueueSize',
      label: 'Redis queue max size',
      component: 'InputNumber',
      componentProps: {
        min: 0,
      },
      show: ({ model }) => model.useRedisQueueForMsgPersistence,
    },
    {
      field: 'credentials.type',
      label: 'Credentials type',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Anonymous',
            value: 'anonymous',
          },
          {
            label: 'Basic',
            value: 'basic',
          },
          {
            label: 'PEM',
            value: 'cert.PEM',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'anonymous',
    },
    {
      field: 'credentials.username',
      label: 'username',
      component: 'Input',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'basic',
    },
    {
      field: 'credentials.password',
      label: 'password',
      component: 'InputPassword',
      ifShow: ({ model }) => model['credentials.type'] === 'basic',
    },
    {
      field: 'credentials.caCert',
      label: 'Server CA certificate file',
      component: 'Upload',
      slot: 'upload',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.cert',
      label: 'Client certificate file',
      component: 'Upload',
      slot: 'upload',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.privateKey',
      label: 'Client private key file',
      component: 'Upload',
      slot: 'upload',
      required: true,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.caCertFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.certFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.privateKeyFileName',
      label: '',
      component: 'Upload',
      required: true,
      show: false,
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
    {
      field: 'credentials.password',
      label: 'Private key password',
      component: 'InputPassword',
      ifShow: ({ model }) => model['credentials.type'] === 'cert.PEM',
    },
  ],
  'org.thingsboard.rule.engine.mail.TbSendEmailNode': [
    {
      field: 'useSystemSmtpSettings',
      label: 'Use system SMTP settings',
      component: 'Checkbox',
      defaultValue: true,
    },
    {
      field: 'smtpProtocol',
      label: 'SMTP protocol',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'SMTP',
            value: 'smtp',
          },
          {
            label: 'SMTPS',
            value: 'smtps',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'smtp',
      required: true,
      show: ({ model }) => !model.useSystemSmtpSettings,
    },
    {
      field: 'smtpHost',
      label: 'SMTP host',
      component: 'Input',
      defaultValue: 'localhost',
      required: true,
      show: ({ model }) => !model.useSystemSmtpSettings,
    },
    {
      field: 'smtpPort',
      label: 'SMTP port',
      component: 'InputNumber',
      defaultValue: 25,
      componentProps: {
        min: 1,
        max: 65535,
      },
      required: true,
      show: ({ model }) => !model.useSystemSmtpSettings,
    },
    {
      field: 'timeout',
      label: 'Timeout ms',
      component: 'InputNumber',
      defaultValue: 10000,
      componentProps: {
        min: 1,
      },
      required: true,
      show: ({ model }) => !model.useSystemSmtpSettings,
    },
    {
      field: 'enableTls',
      label: 'Enable TLS',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => !model.useSystemSmtpSettings,
    },
    {
      field: 'tlsVersion',
      label: 'TLS version',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'TLSv1',
            value: 'TLSv1',
          },
          {
            label: 'TLSv1.1',
            value: 'TLSv1.1',
          },
          {
            label: 'TLSv1.2',
            value: 'TLSv1.2',
          },
          {
            label: 'TLSv1.3',
            value: 'TLSv1.3',
          },
        ],
        allowClear: false,
      },
      defaultValue: 'TLSv1',
      show: ({ model }) => model.enableTls && !model.useSystemSmtpSettings,
    },
    {
      field: 'enableProxy',
      label: 'Enable proxy',
      component: 'Checkbox',
      defaultValue: false,
      show: ({ model }) => !model.useSystemSmtpSettings,
    },
    {
      field: 'proxyHost',
      label: 'Proxy host',
      component: 'Input',
      defaultValue: 'localhost',
      required: true,
      show: ({ model }) => model.enableProxy && !model.useSystemSmtpSettings,
    },
    {
      field: 'proxyPort',
      label: 'Proxy port',
      component: 'InputNumber',
      componentProps: {
        min: 1,
        max: 65535,
      },
      required: true,
      show: ({ model }) => model.enableProxy && !model.useSystemSmtpSettings,
    },
    {
      field: 'proxyUser',
      label: 'Proxy user',
      component: 'Input',
      show: ({ model }) => model.enableProxy && !model.useSystemSmtpSettings,
    },
    {
      field: 'proxyPassword',
      label: 'Proxy password',
      component: 'Input',
      show: ({ model }) => model.enableProxy && !model.useSystemSmtpSettings,
    },
    {
      field: 'username',
      label: 'Username',
      component: 'Input',
      show: ({ model }) => !model.useSystemSmtpSettings,
    },
    {
      field: 'password',
      label: 'Password',
      component: 'InputPassword',
      show: ({ model }) => !model.useSystemSmtpSettings,
    },
  ],
  'org.thingsboard.rule.engine.notification.TbNotificationNode': [
    {
      field: 'templateId',
      label: '模板',
      component: 'ApiSelect',
      componentProps: {
        api: getTemplatesList,
        params: {
          pageSize: 50,
          page: 0,
          sortProperty: 'name',
          sortOrder: 'ASC',
          notificationTypes: 'RULE_NODE',
        },
        listHeight: 100,
        resultField: 'data',
        labelField: 'name',
        valueField: 'id',
        immediate: true,
        objectToJson: true,
        onChange: (e) => console.log(e),
      },
      required: true,
    },
    {
      field: 'targets',
      label: '收件人',
      component: 'ApiSelect',
      componentProps: {
        api: getTargetsList,
        params: {
          pageSize: 50,
          page: 0,
          sortProperty: 'name',
          sortOrder: 'ASC',
          notificationTypes: 'RULE_NODE',
        },
        listHeight: 100,
        resultField: 'data',
        labelField: 'name',
        valueField: 'id.id',
        immediate: true,
        objectToJson: true,
        mode: 'tags',
      },
      required: true,
    },
  ],
  'org.thingsboard.rule.engine.sms.TbSendSmsNode': [
    {
      field: 'numbersToTemplate',
      label: 'Phone Numbers To Template',
      component: 'Input',
      required: true,
      defaultValue: '${userPhone}',
    },
    {
      field: 'smsMessageTemplate',
      label: 'SMS message Template',
      component: 'InputTextArea',
      required: true,
      defaultValue: 'Device ${deviceName} has high temperature ${temp}',
    },
    {
      field: 'useSystemSmsSettings',
      label: 'Use system SMS provider settings',
      component: 'Checkbox',
      defaultValue: false,
    },
    {
      field: 'smsProviderConfiguration.type',
      label: 'SMS 服务商类型',
      component: 'Select',
      componentProps: {
        options: [
          {
            label: 'Twilio',
            value: 'TWILIO',
          },
          {
            label: 'AWS_SNS',
            value: 'AWS_SNS',
          },
        ],
        allowClear: false,
      },
      required: true,
      defaultValue: 'TWILIO',
      ifShow: ({ model }) => !model.useSystemSmsSettings,
    },
  ],
  'org.thingsboard.rule.engine.flow.TbCheckpointNode': [
    {
      field: 'queueName',
      label: '队列',
      component: 'ApiSelect',
      componentProps: () => {
        const params = ref({
          pageSize: 10,
          page: 0,
          sortProperty: 'name',
          sortOrder: 'ASC',
          serviceType: 'TB_RULE_ENGINE',
          textSearch: '',
        });
        return {
          api: getQueues,
          listHeight: 160,
          params: params.value,
          resultField: 'data',
          labelField: 'name',
          showSearch: true,
          valueField: 'name',
          onSearch: useDebounceFn((e) => {
            params.value.textSearch = e;
          }, 300),
          immediate: true,
        };
      },
    },
  ],
  'org.thingsboard.rule.engine.flow.TbRuleChainInputNode': [
    {
      field: 'ruleChainId',
      label: '规则链',
      component: 'ApiSelect',
      componentProps: () => {
        const params = ref({
          pageSize: 10,
          page: 0,
          sortProperty: 'name',
          sortOrder: 'ASC',
          type: 'CORE',
          textSearch: '',
        });
        return {
          listHeight: 100,
          api: getRuleChainList,
          params: params.value,
          resultField: 'data',
          labelField: 'name',
          showSearch: true,
          valueField: 'id.id',
          onSearch: useDebounceFn((e) => {
            params.value.textSearch = e;
          }, 300),
          immediate: true,
        };
      },
    },
  ],
};
